package com.lancoo.ccas52.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas52.arrangecourse.ArrangeCourseService;
import com.lancoo.ccas52.arrangecourse.common.BinaryUtil;
import com.lancoo.ccas52.arrangecourse.dataprocess.GenerateSchedulingData;
import com.lancoo.ccas52.arrangecourse.entities.TeachingClassUnit;
import com.lancoo.ccas52.arrangecourse.entities.TimeslotRoom;
import com.lancoo.ccas52.entity.*;
import com.lancoo.ccas52.mapper.*;
import com.lancoo.ccas52.pojo.common.PageInfo;
import com.lancoo.ccas52.pojo.constant.GlobalConstant;
import com.lancoo.ccas52.pojo.dto.*;
import com.lancoo.ccas52.pojo.vo.*;
import com.lancoo.ccas52.service.*;
import com.lancoo.ccas52.util.BatchInsert;
import com.lancoo.ccas52.util.ExcelFormatUtil;
import com.lancoo.ccas52.util.PagingUtil;
import com.lancoo.ccas52.util.TimeCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 课表 排课
 *
 * @author quin.song
 * @since 2023-03-27
 */
@Service
@Slf4j
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper, Schedule> implements ScheduleService {

    @Resource
    private ScheduleMapper scheduleMapper;
    @Resource
    private ScheduleConflictInfoMapper scheduleConflictInfoMapper;
    @Resource
    private TeachingClassMapper teachingClassMapper;
    @Resource
    private TeachingClassStudentMapper teachingClassStudentMapper;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private RuleRoomProhibitMapper ruleRoomProhibitMapper;
    @Resource
    private RuleCourseProhibitMapper ruleCourseProhibitMapper;
    @Resource
    private RuleTeacherTimeMapper ruleTeacherTimeMapper;
    @Resource
    private MajorMapper majorMapper;

    @Resource
    private BasicRuleService basicRuleService;
    @Resource
    private TeachingClassService teachingClassService;
    @Resource
    private TeacherService teacherService;
    @Resource
    private StudentService studentService;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    @Lazy
    private ArrangeCourseService arrangeCourseService;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private ScheduleConflictInfoService scheduleConflictInfoService;
    @Resource
    private CourseService courseService;
    @Resource
    private CollegeStatusService collegeStatusService;
    @Resource
    private RoomTypeService roomTypeService;


    @Override
    public List<ArrangeTeachingClassDto> getTeachingClassDate(Integer taskId, String campusId, String collegeId, Integer majorProp) {
        //获取课程教学班
        List<ArrangeTeachingClassDto> allTeachingClass = teachingClassMapper.getCourseArrangeTeachingClassDto(taskId, campusId, collegeId, majorProp, null);
        //公共课教学班院系id置为空字符串
        allTeachingClass.stream()
                .filter(teachingClass -> teachingClass.getMajorProp() == 1)
                .forEach(teachingClass -> teachingClass.setCourseCollegeId(""));
        //补充教师信息
        List<Long> teachingClassIds = allTeachingClass.stream().map(ArrangeTeachingClassDto::getTeachingClassId).collect(Collectors.toList());
        Map<String, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds)
                .stream().collect(Collectors.groupingBy( teacher ->  teacher.getTeachingClassId() + "-" + teacher.getHourType()));
        allTeachingClass.forEach(o -> {
            if (o.getTeachingClassType() == 1 ){
                o.setStudentNumber(o.getClassNum());
            }
            //补充教师信息 单独添加，因为教师业务以后可能会变化
            List<Teacher> teachers = teachingClassToTeacher.get(o.getTeachingClassId()+"-"+o.getHourType());
            if (CollUtil.isNotEmpty(teachers)) {
                String teacherIds = StrUtil.join(",", teachers.stream().map(Teacher::getTeacherId).collect(Collectors.toList()));
                String teacherNames = StrUtil.join(",", teachers.stream().map(Teacher::getTeacherName).collect(Collectors.toList()));
                o.setTeacherIds(teacherIds);
                o.setTeacherNames(teacherNames);
            }
        });
        return allTeachingClass;
    }

    @Override
    public List<ArrangeRoomDto> getArrangeRoom(String schoolId, String term, String campusId) {
        List<ArrangeRoomDto> arrangeRoom = roomMapper.getArrangeRoom(schoolId, term, campusId);
        return arrangeRoom;
    }

    @Override
    public List<ArrangePeriod> getArrangeTimeCode(String schoolId, String term, String collegeId) {
        List<ArrangePeriod> periodCode = new ArrayList<>();
        List<RuleWeekDay> weekDays = basicRuleService.getWeekDays(schoolId, term);
        //禁排
        Set<String> timeProhibit = basicRuleService.getTimeProhibit(schoolId, term, collegeId)
                .stream().map(RuleTimeProhibit::getTimeCode).collect(Collectors.toSet());
        weekDays.forEach(weekDay -> {
            weekDay.getPeriodSchemes().forEach(periodScheme -> {
                //第几节
                Integer period = periodScheme.getPeriod();
                //学时code
                String code = weekDay.getWeekDayCode() + String.format("%02d", period);
                //是否属于禁排
                Integer isProhibit = timeProhibit.contains(code) ? 1 : 0;
                //名字格式修改
                String name = "周" + weekDay.getWeekDayCode() + "第" + period + "节";
                periodCode.add(ArrangePeriod.builder().timeCode(code).codeName(name).periodType(periodScheme.getPeriodType()).period(period).isProhibit(isProhibit).build());

            });

        });
        return periodCode;
    }

    @Override
    public List<ArrangeRoomRuleDto> getArrangeRoomProhibit(String schoolId, String term, String campusId, String collegeId) {
        //学院id为null，则去掉禁排规则
        if (ObjUtil.isNull(collegeId)) {
            return new ArrayList<>();
        }
        List<ArrangeRoomRuleDto> arrangeRoomRule = ruleRoomProhibitMapper.getArrangeRoomRuleByTaskId(schoolId, term, campusId, collegeId);
        return arrangeRoomRule;
    }

    @Override
    public List<ArrangeCourseRuleDto> getArrangeCourseProhibit(Integer taskId) {
        List<ArrangeCourseRuleDto> arrangeCourseRule = ruleCourseProhibitMapper.getArrangeCourseRuleByTaskId(taskId);
        return arrangeCourseRule;
    }

    @Override
    public List<ArrangeTeacherRuleDto> getArrangeTeacherTime(String schoolId, String term, String collegeId) {
        //学院id为null，则去掉禁排规则
        if (ObjUtil.isNull(collegeId)) {
            return new ArrayList<>();
        }
        List<ArrangeTeacherRuleDto> arrangeTeacherRule = ruleTeacherTimeMapper.getArrangeTeacherRuleByTaskId(schoolId, term, collegeId);
        return arrangeTeacherRule;
    }

    @Override
    public List<ArrangeScheduleDto> getLockSchedule(Integer taskId, String campusId, Integer isLocked, Integer majorProp, String collegeId) {
        List<ArrangeScheduleDto> scheduleLocked = new ArrayList<>();
        //本学期其他任务课表
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        List<TaskInfo> taskInfos = taskInfoService.lambdaQuery().eq(TaskInfo::getSchoolId, taskInfo.getSchoolId()).eq(TaskInfo::getTerm, taskInfo.getTerm()).list();
        List<Integer> taskIds = taskInfos.stream().map(TaskInfo::getTaskId).filter(o -> !o.equals(taskId)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(taskIds)) {
            scheduleLocked = scheduleMapper.getScheduleLockedByIds(taskIds, campusId, isLocked);
        }
        //获取本学院锁定课表及其他学院课表
        scheduleLocked.addAll(scheduleMapper.getScheduleLocked(taskId, campusId, isLocked, majorProp == null ? null : collegeId));

        if (CollUtil.isEmpty(scheduleLocked)) {
            return scheduleLocked;
        }
        //补充教师信息
        List<Long> teachingClassIds = scheduleLocked.stream().map(ArrangeScheduleDto::getTeachingClassId).collect(Collectors.toList());
        Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds)
                .stream().collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        scheduleLocked.forEach(o -> {
            //补充codeName
            o.setCodeName(TimeCodeUtil.convert(o.getTimeCode()));
            //补充教师信息 单独添加，因为教师业务以后可能会变化
            List<Teacher> teachers = teachingClassToTeacher.get(o.getTeachingClassId());
            if (CollUtil.isNotEmpty(teachers)) {
                String teacherIds = StrUtil.join(",", teachers.stream().map(Teacher::getTeacherId).collect(Collectors.toList()));
                o.setTeacherIds(teacherIds);
            }
        });
        return scheduleLocked;
    }

    @Override
    public void addBathSchedule(Integer taskId, List<Schedule> schedules, String collegeId,Integer majorProp) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        //获取本学期任务
        List<Integer> taskIds = taskInfoService.lambdaQuery().eq(TaskInfo::getSchoolId, taskInfo.getSchoolId()).eq(TaskInfo::getTerm, taskInfo.getTerm()).list()
                .stream().map(TaskInfo::getTaskId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(taskIds)) {
            scheduleMapper.delete(new LambdaUpdateWrapper<Schedule>().in(Schedule::getTaskId, taskIds).eq(ObjUtil.isNotNull(collegeId) && ObjUtil.isNotNull(majorProp), Schedule::getCollegeId, collegeId));
        }
        //批量插入课表，大数据批量插入
        Consumer<List<Schedule>> scheduleConsumer = o -> scheduleMapper.addBatch(o);
        BatchInsert.batchSplitInsert(schedules, scheduleConsumer);
    }

    @Override
    public void addBatchScheduleConflict(Integer taskId, List<ScheduleConflictInfo> scheduleConflicts, List<Long> roomIds) {
        //需要先清除原来的冲突
//        if (CollUtil.isNotEmpty(roomIds)) {
//            scheduleConflictInfoMapper.delete(new LambdaUpdateWrapper<ScheduleConflictInfo>().eq(ScheduleConflictInfo::getTaskId, taskId).in(ScheduleConflictInfo::getRoomId, roomIds));
//        }
        scheduleConflictInfoMapper.delete(new LambdaUpdateWrapper<ScheduleConflictInfo>().eq(ScheduleConflictInfo::getTaskId, taskId));
        //批量插入课表，大数据批量插入
        Consumer<List<ScheduleConflictInfo>> scheduleConflictConsumer = o -> scheduleConflictInfoMapper.addBatch(o);
        BatchInsert.batchSplitInsert(scheduleConflicts, scheduleConflictConsumer);
    }

    @Override
    public void updateScheduleState(List<ArrangeTeachingClassUpdate> arrangeTeachingClassUpdates) {
        //todo 可以根据排课状态批量更新
        List<TeachingClass> teachingClassList = BeanUtil.copyToList(arrangeTeachingClassUpdates, TeachingClass.class);
        teachingClassService.updateBatchById(teachingClassList);
    }

    @Override
    public List<ScheduleConflictInfo> getScheduleConflictInfo(Long teachingClassId) {
        List<ScheduleConflictInfo> list = scheduleConflictInfoService.lambdaQuery().eq(ScheduleConflictInfo::getTeachingClassId, teachingClassId).list();
        fillConflict(list);
        return list;
    }

    @Override
    public PageInfo<TeachingClassCourseDto> getTeachingClassCoursePage(Integer taskId, Page page, Integer state, Integer isLocked, String collegeId, Integer studyNature, Integer majorProp) {
        IPage<TeachingClassCourseDto> teachingClassPage = teachingClassMapper.getCourseTeachingClassForArrange(page, taskId, state, isLocked, collegeId, studyNature, majorProp);
        List<TeachingClassCourseDto> teachingClassList = teachingClassPage.getRecords();
        if (CollUtil.isNotEmpty(teachingClassList)) {
            List<Long> teachingClassIds = teachingClassList.stream().map(TeachingClassCourseDto::getTeachingClassId).collect(Collectors.toList());
            //学生人数
            Map<Long, Integer> studentNumMap = teachingClassStudentMapper.getStudentNumber(teachingClassIds)
                    .stream().collect(Collectors.toMap(TeachingClassCourseDto::getTeachingClassId, TeachingClassCourseDto::getStudentNumber));
            //补充教师信息
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds)
                    .stream().collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            //课表信息
            List<ScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIds(null, teachingClassIds);
            Map<Long, List<ScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(ScheduleDto::getTeachingClassId));
            teachingClassList.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //周次
                a.setCourseWeeks(weekMap.get(a.getTeachingClassId()));
                //课表
                a.setSchedules(scheduleMap.get(a.getTeachingClassId()));
                //学生人数
                a.setStudentNumber(studentNumMap.getOrDefault(a.getTeachingClassId(), 0));
            });
        }
        teachingClassPage.setRecords(teachingClassList);
        return PagingUtil.formatPageResult(teachingClassPage);
    }

    @Override
    public TeachingClassCourseDto getWeekSchedule(Long teachingClassId) {
        List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.lambdaQuery().eq(TeachingClassWeek::getTeachingClassId, teachingClassId).list();
        //课表信息
        List<ScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIds(null, Arrays.asList(teachingClassId));

        return new TeachingClassCourseDto()
                .setCourseWeeks(teachingClassWeekList)
                .setSchedules(scheduleDtoList);
    }

    @Override
    public PageInfo<TeachingClassSegmentDto> getTeachingClassSegmentPage(Integer taskId, Page page, Integer state, String collegeId, Integer studyNature) {
        IPage<TeachingClassSegmentDto> teachingClassPage = teachingClassMapper.getSegmentTeachingClassForArrange(page, taskId, state, collegeId, studyNature);
        List<TeachingClassSegmentDto> teachingClassList = teachingClassPage.getRecords();
        if (CollUtil.isNotEmpty(teachingClassList)) {
            List<Long> teachingClassIds = teachingClassList.stream().map(TeachingClassSegmentDto::getTeachingClassId).collect(Collectors.toList());
            //学生人数
            Map<Long, Integer> studentNumMap = teachingClassStudentMapper.getStudentNumber(teachingClassIds)
                    .stream().collect(Collectors.toMap(TeachingClassCourseDto::getTeachingClassId, TeachingClassCourseDto::getStudentNumber));
            //补充教师信息
            Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds)
                    .stream().collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //填充周次数据
            List<TeachingClassWeek> teachingClassWeekList = teachingClassWeekService.list(new LambdaQueryWrapper<TeachingClassWeek>().in(TeachingClassWeek::getTeachingClassId, teachingClassIds));
            Map<Long, List<TeachingClassWeek>> weekMap = teachingClassWeekList.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
            teachingClassList.forEach(a -> {
                a.setTeachers(teachingClassToTeacher.get(a.getTeachingClassId()));
                //周次
                a.setCourseWeeks(weekMap.get(a.getTeachingClassId()));
                //学生人数
                a.setStudentNumber(studentNumMap.getOrDefault(a.getTeachingClassId(), 0));
            });
        }
        teachingClassPage.setRecords(teachingClassList);
        return PagingUtil.formatPageResult(teachingClassPage);
    }

    @Override
    public Long getAllLockedTeachingClass(Integer taskId, String collegeId, Integer majorProp) {
        Long count = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, taskId)
                .eq(TeachingClass::getFlag, 1)
                .eq(TeachingClass::getIsLocked, 2)
                .eq(StrUtil.isNotBlank(collegeId) ,TeachingClass::getCollegeId, collegeId)
                .eq(TeachingClass::getMajorProp, majorProp)
                .ne(TeachingClass::getTeachingClassType, 3).count();
        return count;
    }

    @Override
    public boolean updateLock(Integer isLocked, List<Long> teachingClassIds) {
        return teachingClassService.lambdaUpdate()
                .set(TeachingClass::getIsLocked, isLocked)
                .in(TeachingClass::getTeachingClassId, teachingClassIds).update();
    }

    @Override
    public Boolean allNormalLocal(Integer taskId, String collegeId, Integer majorProp) {
        if(ObjUtil.isNull(collegeId)){
            //锁定全部教学班
            teachingClassService.lambdaUpdate().set(TeachingClass::getIsLocked, 2)
                    .eq(TeachingClass::getTaskId, taskId)
                    .eq(TeachingClass::getScheduleState, 1).update();
            return true;
        }
        //修改状态
        CollegeStatus collegeStatus = new CollegeStatus().setTaskId(taskId).setCollegeId(collegeId).setIsLock(1);
        collegeStatusService.saveOrUpdate(collegeStatus, new LambdaQueryWrapper<CollegeStatus>()
                .eq(CollegeStatus::getTaskId, taskId)
                .eq(CollegeStatus::getCollegeId, collegeId));
        teachingClassService.lambdaUpdate().set(TeachingClass::getIsLocked, 2)
                .eq(TeachingClass::getTaskId, taskId)
                .eq(StrUtil.isNotBlank(collegeId) ,TeachingClass::getCollegeId, collegeId)
                .eq(majorProp != null,TeachingClass::getMajorProp, majorProp)
                .eq(TeachingClass::getScheduleState, 1).update();

        return true;
    }

    @Override
    public Boolean allUnLock(Integer taskId, String collegeId, Integer majorProp) {
        teachingClassService.lambdaUpdate().set(TeachingClass::getIsLocked, 1)
                .eq(TeachingClass::getTaskId, taskId)
                .eq(StrUtil.isNotBlank(collegeId) ,TeachingClass::getCollegeId, collegeId)
                .eq(majorProp != null,TeachingClass::getMajorProp, majorProp).update();
        //修改状态
        CollegeStatus collegeStatus = new CollegeStatus().setTaskId(taskId).setCollegeId(collegeId).setIsLock(0);
        collegeStatusService.saveOrUpdate(collegeStatus, new LambdaQueryWrapper<CollegeStatus>()
                .eq(CollegeStatus::getTaskId, taskId)
                .eq(CollegeStatus::getCollegeId, collegeId));
        return true;
    }

    @Override
    public CollegeStatus arrangeSubmit(CollegeStatus collegeStatus){
        //仅教务管理员排课，则修改全部学院状态
        TaskInfo taskInfo = taskInfoService.lambdaQuery().eq(TaskInfo::getTaskId, collegeStatus.getTaskId()).one();
        if (taskInfo.getArrangeAuthority().equals(0)) {
            List<CollegeStatus> collegeStatusList = new ArrayList<>();
            majorMapper.getCollegeByTaskId(collegeStatus.getTaskId()).forEach(a -> {
                collegeStatusList.add(new CollegeStatus()
                        .setTaskId(collegeStatus.getTaskId())
                        .setCollegeId(a.getCollegeId())
                        .setArrangeSubmit(1)
                        .setIsLock(1));
            });
            //教务管理员
            collegeStatusList.add(new CollegeStatus()
                    .setTaskId(collegeStatus.getTaskId())
                    .setCollegeId("")
                    .setArrangeSubmit(1)
                    .setIsLock(1));
            collegeStatusService.saveBatch(collegeStatusList);
            allNormalLocal(collegeStatus.getTaskId(),null, null);
            return collegeStatus;
        }
        //教务和院系管理员一起排课
        collegeStatusService.saveOrUpdate(collegeStatus);
        //锁定该院系正常课表
        if (collegeStatus.getArrangeSubmit().equals(1)) {
            //教务管理员
            if ("".equals(collegeStatus.getCollegeId())) {
                allNormalLocal(collegeStatus.getTaskId(),collegeStatus.getCollegeId(), 1);
            }else {
                allNormalLocal(collegeStatus.getTaskId(),collegeStatus.getCollegeId(), 2);
            }
        }
        return collegeStatus;
    }

    @Override
    public void removeArrangeSubmit(CollegeStatus collegeStatus) {
        collegeStatusService.lambdaUpdate()
                .eq(CollegeStatus::getTaskId,collegeStatus.getTaskId())
                .eq(CollegeStatus::getCollegeId,collegeStatus.getCollegeId())
                .remove();
    }

    @Override
    public PublishStatisticsArrange getPublishStatisticsArrange(Integer taskId, String collegeId, Integer majorProp) {
        PublishStatisticsArrange publishStatisticsArrange = new PublishStatisticsArrange();
        PublishStatisticsArrange.Statistics courseCount = new PublishStatisticsArrange.Statistics();
        PublishStatisticsArrange.Statistics segmentCount = new PublishStatisticsArrange.Statistics();
        long courseTotalNum = 0;
        long courseNormalNum = 0;
        long courseConflictNum = 0;
        long segmentTotalNum = 0;
        //获取教学班状态
        List<ArrangeStatistics> arrangeStatistics = teachingClassMapper.getArrangeStatistics(taskId, collegeId, majorProp);
        for (ArrangeStatistics arrangeStatistic : arrangeStatistics) {
            if (arrangeStatistic.getFlag().equals(1)) {
                courseTotalNum++;
                if (arrangeStatistic.getScheduleState().equals(1)) {
                    courseNormalNum++;
                } else if (arrangeStatistic.getScheduleState().equals(2)) {
                    courseConflictNum++;
                }
            } else if (arrangeStatistic.getFlag().equals(2)) {
                segmentTotalNum++;
            }
        }
        courseCount.setTotalNum(courseTotalNum).setCompleteNum(courseNormalNum + courseConflictNum).setNormalNum(courseNormalNum).setConflictNum(courseConflictNum);
        segmentCount.setTotalNum(segmentTotalNum);
        return publishStatisticsArrange.setCourseCount(courseCount).setSegmentCount(segmentCount);
    }

    @Override
    public List<ScheduleConflictInfo> autoArrangement(Integer taskId, String collegeId, Integer majorProp) {
        arrangeCourseService.algService(taskId, collegeId, majorProp);
        //返回冲突
        List<ScheduleConflictInfo> scheduleConflictInfos = scheduleConflictInfoMapper.selectList(new LambdaQueryWrapper<ScheduleConflictInfo>().eq(ScheduleConflictInfo::getTaskId, taskId));
        fillConflict(scheduleConflictInfos);
        return scheduleConflictInfos;
    }

    /**
     * 填充冲突信息 将id转换为字符串填到对应冲突字符串后面
     *
     * @param scheduleConflictInfos
     */
    public void fillConflict(List<ScheduleConflictInfo> scheduleConflictInfos) {
        //填充冲突字符串
        List<TeachingClass> teachingClassList = new ArrayList<>();
        List<Room> roomList = new ArrayList<>();
        List<Teacher> teacherList = new ArrayList<>();
        List<Student> studentList = new ArrayList<>();
        Map<Integer, List<ScheduleConflictInfo>> scheduleConflictInfoMap = scheduleConflictInfos.stream().collect(Collectors.groupingBy(ScheduleConflictInfo::getConflictType));
        List<Long> clashUnitIds = new ArrayList<>();
        //获取冲突类型 对应实体类
        if (CollUtil.isNotEmpty(scheduleConflictInfoMap.get(1))) {
            clashUnitIds = scheduleConflictInfoMap.get(1).stream().map(ScheduleConflictInfo::getClashUnit).collect(Collectors.toList());
            if (!clashUnitIds.isEmpty()) {
                teachingClassList = teachingClassService.listByIds(clashUnitIds);
            }
        }
        if (CollUtil.isNotEmpty(scheduleConflictInfoMap.get(2))) {
            clashUnitIds = scheduleConflictInfoMap.get(2).stream().map(ScheduleConflictInfo::getClashUnit).collect(Collectors.toList());
            if (!clashUnitIds.isEmpty()) {
                roomList = roomMapper.selectBatchIds(clashUnitIds);
            }
        }
        if (CollUtil.isNotEmpty(scheduleConflictInfoMap.get(3))) {
            clashUnitIds = scheduleConflictInfoMap.get(3).stream().map(ScheduleConflictInfo::getClashUnit).collect(Collectors.toList());
            if (!clashUnitIds.isEmpty()) {
                teacherList = teacherService.listByIds(clashUnitIds);
            }
        }
        if (CollUtil.isNotEmpty(scheduleConflictInfoMap.get(4))) {
            clashUnitIds = scheduleConflictInfoMap.get(4).stream().map(ScheduleConflictInfo::getClashUnit).collect(Collectors.toList());
            if (!clashUnitIds.isEmpty()) {
                studentList = studentService.listByIds(clashUnitIds);
            }
        }

        //字符串填充
        for (ScheduleConflictInfo scheduleConflictInfo : scheduleConflictInfos) {
            if (scheduleConflictInfo.getConflictType() == 1) {
                Optional<TeachingClass> teachingClass = teachingClassList.stream().filter(b -> b.getTeachingClassId().equals(scheduleConflictInfo.getClashUnit())).findFirst();
                teachingClass.ifPresent(aClass -> scheduleConflictInfo.setConflictReason(scheduleConflictInfo.getConflictReason() + aClass.getTeachingClassName()));
            }
            if (scheduleConflictInfo.getConflictType() == 2) {
                Optional<Room> room = roomList.stream().filter(b -> b.getRoomId().equals(scheduleConflictInfo.getClashUnit())).findFirst();
                room.ifPresent(value -> scheduleConflictInfo.setConflictReason(scheduleConflictInfo.getConflictReason() + value.getRoomName()));
            }
            if (scheduleConflictInfo.getConflictType() == 3) {
                Optional<Teacher> teacher = teacherList.stream().filter(b -> b.getTeacherId().equals(scheduleConflictInfo.getClashUnit())).findFirst();
                teacher.ifPresent(value -> scheduleConflictInfo.setConflictReason(scheduleConflictInfo.getConflictReason() + value.getTeacherName()));
            }
            if (scheduleConflictInfo.getConflictType() == 4) {
                Optional<Student> student = studentList.stream().filter(b -> b.getStudentId().equals(scheduleConflictInfo.getClashUnit())).findFirst();
                student.ifPresent(value -> scheduleConflictInfo.setConflictReason(scheduleConflictInfo.getConflictReason() + value.getStudentName()));
            }
        }
    }

    @Override
    public TeachingClassCourseDto getTeachingClassById(Long teachingClassId) {
        return teachingClassMapper.getCourseTeachingClassById(teachingClassId);
    }

    @Override
    public List<Schedule> generateTeachingClassUnit(Integer taskId, Long teachingClassId) {
        //待生成初始化课表
        List<Schedule> scheduleList = new ArrayList<>();
        //获取课程教学班
        List<ArrangeTeachingClassDto> teachingClassCourse = teachingClassMapper.getCourseArrangeTeachingClassDto(taskId, null, null, null, teachingClassId);
        //公共课教学班院系id置为空字符串
        teachingClassCourse.stream()
                .filter(teachingClass -> teachingClass.getMajorProp() == 1)
                .forEach(teachingClass -> teachingClass.setCourseCollegeId(""));

        GenerateSchedulingData generateSchedulingData = new GenerateSchedulingData();
        LinkedList<TeachingClassUnit> teachingClassUnits = generateSchedulingData.convertToTeachingClassUnit(taskId, teachingClassCourse, 0);

        teachingClassUnits.forEach(a -> {
            for (int i = 0; i < a.getConnectSection(); i++) {
                scheduleList.add(new Schedule().setTaskId(taskId)
                        .setTeachingClassId(a.getTeachingClassId())
                        .setTeachingClassName(a.getTeachingClassName())
                        .setCourseId(a.getCourseId())
                        .setCourseName(a.getCourseName())
                        .setHourType(a.getTeachingType())
                        .setWeek(a.getClassWeeks())
                        .setConnectSection(a.getConnectSection())
                        .setRoomId(a.getRoomId())
                        .setGroupIdent(a.getGroupIdent())
                        .setCollegeId(a.getCollegeId()));
            }
        });
        //批量插入课表，大数据批量插入
        Consumer<List<Schedule>> scheduleConsumer = o -> scheduleMapper.addBatch(o);
        BatchInsert.batchSplitInsert(scheduleList, scheduleConsumer);
        return scheduleList;
    }

    @Override
    public Boolean removeSchedule(Long teachingClassId) {
        this.lambdaUpdate().eq(Schedule::getTeachingClassId, teachingClassId).remove();
        //更新教学班排课状态为待排
        teachingClassService.lambdaUpdate()
                .eq(TeachingClass::getTeachingClassId, teachingClassId)
                .set(TeachingClass::getScheduleState, 3).update();
        return true;
    }

    @Override
    public PageInfo<VenueSessionVo> getVenueSession(Integer currentPage, Integer pageSize, Integer taskId, String weeks, String timeCodes, Long roomId, String collegeId, ArrangeTeachingClassDto teachingClass) {
        List<VenueSessionVo> venueSessionVos = new ArrayList<>();
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        //可用的 场地节次
        LinkedList<TimeslotRoom> timeslotRooms = arrangeCourseService.getAvailableTimeslotRoomList(taskInfo.getSchoolId(), taskInfo.getTerm(),
                taskId, Integer.parseInt(weeks, 2) == 0 ? null : weeks, timeCodes, roomId, collegeId, teachingClass);

        if (CollUtil.isEmpty(timeslotRooms)) {
            return new PageInfo<>();
        }

        // 返回连上的场地节次
        List<TimeslotRoom[]> consecutiveSessions = findConsecutiveSessions(timeslotRooms, teachingClass.getConnectSection());
        PageInfo<TimeslotRoom[]> pages = PagingUtil.getPages(currentPage, pageSize, consecutiveSessions);
        pages.getList().forEach(consecutiveSession -> {
            //对分组的数据取周次与运算
            String resultWeek = Arrays.stream(consecutiveSession)
                    .map(TimeslotRoom::getWeeks)
                    .reduce(BinaryUtil::binaryAnd)
                    .orElse("");
            //可用节次
            String resultSession = "{}[{}节]";
            String week = TimeCodeUtil.DAY_NAME.get(TimeCodeUtil.DAY_CODE.indexOf(consecutiveSession[0].getTimeslotCode().substring(0, 2)));
            List<Integer> sectionList = Arrays.stream(consecutiveSession).map(a -> Integer.valueOf(a.getTimeslotCode().substring(2))).distinct().sorted().collect(Collectors.toList());
            venueSessionVos.add(new VenueSessionVo()
                    .setRoomId(consecutiveSession[0].getRoomId())
                    .setRoomName(consecutiveSession[0].getRoomName())
                    .setWeeks(resultWeek)
                    .setSession(StrUtil.format(resultSession, week, StrUtil.join("、", sectionList)))
                    .setTimeCode(StrUtil.join("、", Arrays.stream(consecutiveSession).map(TimeslotRoom::getTimeslotCode).collect(Collectors.toList())))
                    .setBuildingId(consecutiveSession[0].getBuildingId())
                    .setBuildingName(consecutiveSession[0].getBuildingName()));
        });

        return new PageInfo<VenueSessionVo>()
                .setCurrentPage(pages.getCurrentPage())
                .setPageSize(pages.getPageSize())
                .setTotal(pages.getTotal())
                .setPages(pages.getPages())
                .setList(venueSessionVos);
    }

    @Override
    public PageInfo<VenueSessionVo> getFreeVenueSession(Integer currentPage, Integer pageSize, Integer taskId, String weeks, String sections, Integer connectSection, Integer buildingId, Integer roomType, String weekSet, Long roomId, String collegeId) {
        List<VenueSessionVo> venueSessionVos = new ArrayList<>();
        TaskInfo taskInfo = taskInfoService.getById(taskId);

        //可用的 场地节次
        LinkedList<TimeslotRoom> timeslotRooms = arrangeCourseService.getAvailableTimeslotRoomList(taskInfo.getSchoolId(), taskInfo.getTerm(),
                taskId, Integer.parseInt(weeks, 2) == 0 ? null : weeks, null, roomId, collegeId, null);

        if (CollUtil.isEmpty(timeslotRooms)) {
            return new PageInfo<>();
        }
        //符合条件的场地节次
        List<TimeslotRoom> conditionsTimeslotRooms = timeslotRooms.stream()
                .filter(timeslotRoom -> buildingId == null || timeslotRoom.getBuildingId().equals(buildingId))
                .filter(timeslotRoom -> roomType == null || timeslotRoom.getRoomType().equals(roomType))
                .filter(timeslotRoom -> StrUtil.isBlank(sections) || Arrays.asList(sections.split(",")).contains(timeslotRoom.getTimeslotCode().substring(2)))
                .filter(timeslotRoom -> StrUtil.isBlank(weekSet) || Arrays.asList(weekSet.split(",")).contains(timeslotRoom.getTimeslotCode().substring(0, 2)))
                .collect(Collectors.toList());
        // 返回连上的场地节次
        List<TimeslotRoom[]> consecutiveSessions = findConsecutiveSessions(conditionsTimeslotRooms, connectSection);
        PageInfo<TimeslotRoom[]> pages = PagingUtil.getPages(currentPage, pageSize, consecutiveSessions);
        pages.getList().forEach(consecutiveSession -> {
            //对分组的数据取周次与运算
            String resultWeek = Arrays.stream(consecutiveSession)
                    .map(TimeslotRoom::getWeeks)
                    .reduce(BinaryUtil::binaryAnd)
                    .orElse("");
            //可用节次
            String resultSession = "{}[{}节]";
            String week = TimeCodeUtil.DAY_NAME.get(TimeCodeUtil.DAY_CODE.indexOf(consecutiveSession[0].getTimeslotCode().substring(0, 2)));
            List<Integer> sectionList = Arrays.stream(consecutiveSession).map(a -> Integer.valueOf(a.getTimeslotCode().substring(2))).distinct().sorted().collect(Collectors.toList());
            venueSessionVos.add(new VenueSessionVo()
                    .setRoomId(consecutiveSession[0].getRoomId())
                    .setRoomName(consecutiveSession[0].getRoomName())
                    .setWeeks(resultWeek)
                    .setSession(StrUtil.format(resultSession, week, StrUtil.join("、", sectionList)))
                    .setBuildingId(consecutiveSession[0].getBuildingId())
                    .setBuildingName(consecutiveSession[0].getBuildingName()));
        });
        return new PageInfo<VenueSessionVo>()
                .setCurrentPage(pages.getCurrentPage())
                .setPageSize(pages.getPageSize())
                .setTotal(pages.getTotal())
                .setPages(pages.getPages())
                .setList(venueSessionVos);
    }

    /**
     * 根据连上节次获取 连上组合
     *
     * @param timeslotRoomList
     * @param consecutiveCount
     * @return
     */
    public List<TimeslotRoom[]> findConsecutiveSessions(List<TimeslotRoom> timeslotRoomList, int consecutiveCount) {
        List<TimeslotRoom[]> consecutiveSessions = new ArrayList<>();
        //根据room分组
        Map<Long, List<TimeslotRoom>> groupSessions = timeslotRoomList.stream()
                .collect(Collectors.groupingBy(TimeslotRoom::getRoomId));

        for (List<TimeslotRoom> timeslotRooms : groupSessions.values()) {
            // 根据 timeCode 进行排序
            timeslotRooms.sort(Comparator.comparing(TimeslotRoom::getTimeslotCode));
            //遍历每一个节次
            for (int i = 0; i < timeslotRooms.size() - consecutiveCount + 1; i++) {
                //选择连着的连上节次判断是否符合要求
                boolean isConsecutive = IntStream.range(i + 1, i + consecutiveCount)
                        .allMatch(j -> Integer.parseInt(timeslotRooms.get(j).getTimeslotCode()) - Integer.parseInt(timeslotRooms.get(j - 1).getTimeslotCode()) == 1);
                //添加上午下午判断
                boolean isPeriodType = IntStream.range(i + 1, i + consecutiveCount)
                        .allMatch(j -> timeslotRooms.get(j).getPeriodType().equals(timeslotRooms.get(j - 1).getPeriodType()));

                if (isConsecutive && isPeriodType) {
                    consecutiveSessions.add(timeslotRooms.subList(i, i + consecutiveCount).toArray(new TimeslotRoom[0]));
                }
            }
        }
        return consecutiveSessions;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ScheduleDto> updateVenueSession(List<Schedule> startSchedule, List<Schedule> stopSchedule, Long teachingClassId) {
        List<Schedule> addSchedule = new ArrayList<>();
        List<Schedule> updateSchedule = new ArrayList<>();
        List<Schedule> deleteSchedule = new ArrayList<>();
        //原来的场地节次 要么更新 都为0时删除。并且每个课表信息应该一致
        if (Integer.parseInt(startSchedule.get(0).getWeek(), 2) == 0) {
            deleteSchedule.addAll(startSchedule);
        } else {
            updateSchedule.addAll(startSchedule);
        }
        //新的场地节次 要么新增 要么更新.当存在场地节次一致时，则是更新
        this.lambdaQuery().eq(Schedule::getTeachingClassId, teachingClassId).list().forEach(schedule -> {
            if (StrUtil.isNotBlank(schedule.getTimeCode()) && ObjUtil.isNotNull(schedule.getRoomId())) {
                stopSchedule.forEach(stop -> {
                    //场地节次一致时， 更新周次信息
                    if (schedule.getRoomId().equals(stop.getRoomId()) && schedule.getTimeCode().equals(stop.getTimeCode()) && schedule.getHourType().equals(stop.getHourType())) {
                        stop.setId(schedule.getId());
                        stop.setWeek(BinaryUtil.binaryOR(schedule.getWeek(), stop.getWeek()));
                        updateSchedule.add(stop);
                    }
                });
            }
        });
        addSchedule = stopSchedule.stream().filter(schedule -> schedule.getId() == null).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(addSchedule)) {
            this.saveBatch(addSchedule);
        }
        if (CollUtil.isNotEmpty(updateSchedule)) {
            this.updateBatchById(updateSchedule);
        }
        if (CollUtil.isNotEmpty(deleteSchedule)) {
            this.removeByIds(deleteSchedule);
        }
        return scheduleMapper.getScheduleByTeachingClassIds(null, Collections.singletonList(teachingClassId));
    }

    @Override
    public List<DetermineStatistics> arrangeDetermineStatistics(Integer taskId, String collegeId, String keyWord, Integer arrangeSubmit) {
        List<DetermineStatistics> determineStatisticsList = new ArrayList<>();
        //获取待显示的学院
        List<CollegeDto> college = majorMapper.getCollegeStatus(taskId, collegeId, keyWord, arrangeSubmit);
        if (CollUtil.isNotEmpty(college)) {
            //获取全部教学班 分组
            Map<String, List<TeachingClass>> teachingClassByCollege = teachingClassService.lambdaQuery()
                    .select(TeachingClass::getTeachingClassId, TeachingClass::getCourseId, TeachingClass::getCollegeId, TeachingClass::getFlag)
                    .eq(TeachingClass::getTaskId, taskId).ne(TeachingClass::getTeachingClassType, 3)
                    .in(TeachingClass::getCollegeId, college.stream().map(CollegeDto::getCollegeId).collect(Collectors.toList()))
                    .list()
                    .stream()
                    .collect(Collectors.groupingBy(TeachingClass::getCollegeId));

            //获取全部课表数据
            List<Long> teachingClassIds = teachingClassByCollege.values()
                    .stream()
                    .flatMap(Collection::stream)
                    .map(TeachingClass::getTeachingClassId)
                    .collect(Collectors.toList());
            List<ScheduleStatistics> scheduleStatistics = CollUtil.isEmpty(teachingClassIds) ? new ArrayList<>() : scheduleMapper.getScheduleStatistics(teachingClassIds);

            //遍历学院赋值
            for (CollegeDto collegeDto : college) {
                //该学院下的教学班
                List<TeachingClass> list = teachingClassByCollege.getOrDefault(collegeDto.getCollegeId(), Collections.emptyList());
                //该学院下的课表数据
                List<ScheduleStatistics> scheduleList = scheduleStatistics.stream()
                        .filter(a -> list.stream().anyMatch(tc -> tc.getTeachingClassId().equals(a.getTeachingClassId())))
                        .collect(Collectors.toList());

                determineStatisticsList.add(new DetermineStatistics()
                        .setCollegeId(collegeDto.getCollegeId())
                        .setCollegeName(collegeDto.getCollegeName())
                        .setSegmentNum(list.stream().filter(a -> a.getFlag().equals(2)).map(TeachingClass::getCourseId).distinct().count())
                        .setCourseNum(list.stream().filter(a -> a.getFlag().equals(1)).map(TeachingClass::getCourseId).distinct().count())
                        .setTeachingClassNum(list.size())
                        .setCourseTeachingClassNum(list.stream().filter(a -> a.getFlag().equals(1)).count())
                        .setSegmentTeachingClassNum(list.stream().filter(a -> a.getFlag().equals(2)).count())
                        .setWeekSectionNum(scheduleList.stream().mapToLong(ScheduleStatistics::getTotalNum).sum())
                        .setUnArrangeNum(scheduleList.stream().mapToLong(ScheduleStatistics::getUnArrangeNum).sum())
                        .setArrangeSubmit(collegeDto.getArrangeSubmit()));
            }
        }
        return determineStatisticsList;
    }

    @Override
    public List<ScheduleUnitGroupVo> getUnArrangeSchedule(Integer taskId) {
        List<ScheduleUnitGroupVo> scheduleUnitGroupVoList = new ArrayList<>();
        List<ScheduleUnitVo> emptyScheduleUnit = scheduleMapper.getEmptyScheduleUnit(taskId);
        if (CollUtil.isEmpty(emptyScheduleUnit)) {
            return scheduleUnitGroupVoList;
        }
        //学院id 学院名
        List<Long> courseId = emptyScheduleUnit.stream().map(ScheduleUnitVo::getCourseId).distinct().collect(Collectors.toList());
        Map<Long, Course> courseMap = courseService.lambdaQuery().select(Course::getCourseId, Course::getCollegeId, Course::getCollegeName).in(Course::getCourseId, courseId).list()
                .stream().collect(Collectors.toMap(Course::getCourseId, a -> a));
        //过滤掉未提交院系的数据
        List<String> collegeIds = collegeStatusService.lambdaQuery().eq(CollegeStatus::getTaskId, taskId).list()
                .stream().map(CollegeStatus::getCollegeId).collect(Collectors.toList());
        //要显示该课程未排的数据
        List<Long> courseIds = courseMap.values().stream().filter(a -> collegeIds.contains(a.getCollegeId())).map(Course::getCourseId).distinct().collect(Collectors.toList());

        //教师id 教师名
        List<Long> teachingClassIds = emptyScheduleUnit.stream().map(ScheduleUnitVo::getTeachingClassId).distinct().collect(Collectors.toList());
        Map<Long, List<Teacher>> teachingClassToTeacher = teacherService.getTeacherByTeachingClassIds(teachingClassIds)
                .stream().collect(Collectors.groupingBy(Teacher::getTeachingClassId));
        Iterator<ScheduleUnitVo> iterator = emptyScheduleUnit.iterator();
        while (iterator.hasNext()) {
            ScheduleUnitVo scheduleUnitVo = iterator.next();
            //排除未提交学院未排节次
            if (!courseIds.contains(scheduleUnitVo.getCourseId())) {
                iterator.remove();
                continue;
            }
            Course course = courseMap.get(scheduleUnitVo.getCourseId());
            if (course != null) {
                scheduleUnitVo.setCollegeId(course.getCollegeId());
                scheduleUnitVo.setCollegeName(course.getCollegeName());
            }
            List<Teacher> teachers = teachingClassToTeacher.get(scheduleUnitVo.getTeachingClassId());
            if (CollUtil.isNotEmpty(teachers)) {
                scheduleUnitVo.setTeachers(teachers);
            }
        }
        //根据唯一标识分组
        scheduleUnitGroupVoList = emptyScheduleUnit.stream()
                .collect(Collectors.groupingBy(ScheduleUnitVo::getGroupIdent, LinkedHashMap::new, Collectors.toList()))
                .values().stream()
                .map(value -> new ScheduleUnitGroupVo().setScheduleUnitVos(value))
                .collect(Collectors.toList());
        return scheduleUnitGroupVoList;
    }

    @Override
    public String courseToExcel(Integer taskId, Integer state, String collegeId, String collegeName, Integer studyNature, Integer majorProp) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/课程课表编排-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);

        Page<TeachingClassCourseDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassCourseDto> teachingClassPage = this.getTeachingClassCoursePage(taskId, page, state, null, collegeId, studyNature, majorProp);
        List<TeachingClassCourseDto> resultList = teachingClassPage.getList();
        String title = "{}课表编排(课程)  \n  {}";
        writer.merge(10, StrUtil.format(title, taskInfo.getSchoolName(), taskInfo.getTermName()), false);
        writer.setRowHeight(0, 40);
        String filterTem = "开课单位:{}    修读性质:{}    排课状态:{}     共:{}个教学班     导出时间:{} ";
        String filter = StrUtil.format(filterTem, StrUtil.isBlank(collegeId) ? "全部院系  " : collegeName,
                ObjUtil.isNull(studyNature) ? "全部" : (studyNature == 1 ? "主修" : "辅修"),
                ObjUtil.isNull(state) ? "全部" : (state == 1 ? "已排（正常）" : (state == 2 ? "已排（冲突）" : "待排")),
                resultList.size(), DateUtil.now());
        writer.merge(10, filter, false);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("编号", "名称", "开课单位", "修读性质", "周次(小周)", "周学时分布(讲授-实验-上机-其他)", "教学班名称", "任课教师", "班级人数", "场地节次", "排课状态"));
        List<String> row;
        Map<Integer, String> roomTypeMap = roomTypeService.lambdaQuery().eq(RoomType::getSchoolId, taskInfo.getSchoolId())
                .eq(RoomType::getTerm, taskInfo.getTerm()).list()
                .stream().collect(Collectors.toMap(RoomType::getId, RoomType::getTypeName));
        for (TeachingClassCourseDto item : resultList) {
            //任课教师名称
            String teacherName = ExcelFormatUtil.getTeacherName(item.getTeachers());
            //周学时
            String weekDistribution = ExcelFormatUtil.getWeekHourString(item.getCourseWeeks(),roomTypeMap);
            //周次
            String weeks = ExcelFormatUtil.getWeekString(item.getCourseWeeks());
            //场地节次
            String siteSection = ExcelFormatUtil.getSiteSection(item.getSchedules());
            row = Arrays.asList(item.getTeachingClassId().toString(), item.getCourseName(), item.getCollegeName(), item.getStudyNature() == 1 ? "主修" : "辅修",
                    weeks, weekDistribution, item.getTeachingClassName(), teacherName, item.getStudentNumber().toString(), siteSection, item.getState() == 1 ? "已排课" : "未排课");
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel/" + storePath;
    }

    @Override
    public String segmentToExcel(Integer taskId, Integer state, String collegeId, String collegeName, Integer studyNature) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/环节课表编排-" + LocalDate.now() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);

        Page<TeachingClassSegmentDto> page = new Page<>(1, -1);
        PageInfo<TeachingClassSegmentDto> teachingClassPage = this.getTeachingClassSegmentPage(taskId, page, state, collegeId, studyNature);
        List<TeachingClassSegmentDto> resultList = teachingClassPage.getList();
        String title = "{}课表编排(环节)  \n  {}";
        writer.merge(7, StrUtil.format(title, taskInfo.getSchoolName(), taskInfo.getTermName()), false);
        writer.setRowHeight(0, 40);
        String filterTem = "开课单位:{}   修读性质:{}    共:{}个教学班   导出时间:{} ";
        String filter = StrUtil.format(filterTem, StrUtil.isBlank(collegeId) ? "全部院系  " : collegeName,
                ObjUtil.isNull(studyNature) ? "全部" : (studyNature == 1 ? "主修" : "辅修"),
                teachingClassPage.getTotal(), DateUtil.now());
        writer.merge(7, filter, false);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("编号", "环节名称", "开课单位", "修读性质", "教学班名称", "任课教师", "班级人数", "周次(小周)"));
        List<String> row;
        for (TeachingClassSegmentDto item : resultList) {
            //任课教师名称
            String teacherName = ExcelFormatUtil.getTeacherName(item.getTeachers());
            //周次
            String weeks = ExcelFormatUtil.getWeekString(item.getCourseWeeks());
            row = Arrays.asList(item.getTeachingClassId().toString(), item.getSegmentName(), item.getCollegeName(), item.getStudyNature() == 1 ? "主修" : "辅修",
                    item.getTeachingClassName(), teacherName, item.getStudentNumber().toString(), weeks);
            rows.add(row);
        }
        writer.write(rows, false);
        ExcelFormatUtil.setFont(writer);
        writer.close();
        return GlobalConstant.ACCESS_PATH + "/static/OutputExcel/" + storePath;
    }


}
